#
# Define configuration variables
#

-include etc/build.conf

BASE_DIR         ?= ../base
REPOSITORIES     ?= $(BASE_DIR:%base=%base-linux) $(BASE_DIR)
VERBOSE          ?= @
VERBOSE_DIR      ?= --no-print-directory
VERBOSE_MK       ?= @
LIB_CACHE_DIR    ?= $(PWD)/var/libcache
LIB_PROGRESS_LOG ?= $(PWD)/progress.log
UNDERLINE        ?= true

# expand "~" characters and relative path names
ABS_REPOSITORIES := $(realpath $(shell echo $(REPOSITORIES)))


#
# Determine the right versions for the used tools.
#
# Tools that do not involve incompatibilities across different
# Unix platforms are not wrapped by make variables.
#

-include etc/tools.conf

TAC              ?= tac
GNU_FIND         ?= find

#
# Find out about the destination to build
#
DST_DIRS = $(filter-out all clean bin cleanall single_target,$(MAKECMDGOALS))

ifeq ($(MAKECMDGOALS),)
DST_DIRS = .
endif

#
# Detect user who has not read the Genode documentation.
# When Debian stable features make version 3.81, we will
# remove this check.
#
ifeq ($(realpath .),)
$(error Your version of GNU make does not support realpath. Please use version 3.81 or higher)
endif

#
# Helper to find targets in repositories
# The sed command is just there to replace /./ by /. This happens when DST_DIRS = .
#
find_src_target_mk     = $(GNU_FIND) $$i/src/$@ -name target.mk 2>/dev/null | sed "s/\/\.\//\//g"
find_all_src_target_mk = for i in $(REPOSITORIES); do $(find_src_target_mk); done

#
# If more that zero destinations are specified, build them
#
ifneq ($(DST_DIRS),)
all:: $(DST_DIRS)

.PHONY: $(DST_DIRS)

#
# Reset library-build log
#
# The 'progress' file contains the names of the already processed libraries
# of the current build process. Before considering to process any library,
# the build system checks if the library is already present in the 'progress'
# file and, if yes, skips it.
#
# Only reset the library build log before building the first target, not
# for each target.
#
$(firstword $(DST_DIRS))::
	@echo "#" > $(LIB_PROGRESS_LOG)
	@echo "# Library build progress log - generated by build.mk and lib.mk" >> $(LIB_PROGRESS_LOG)
	@echo "#" >> $(LIB_PROGRESS_LOG)

#
# First, we check if any target.mk files exist in the specified src directory.
# If there exist any target.mk files, we revisit each repository and build
# them.
#
$(DST_DIRS)::
	@test "`$(find_all_src_target_mk)`" != "" || echo Error: non-existing target '$@'
	$(VERBOSE_MK)set -e; for i in $(REPOSITORIES); do \
	  for j in `$(find_src_target_mk)`; do \
	    $(MAKE) $(VERBOSE_DIR) single_target SINGLE_SRC=$$j REP_DIR=$$i; done; done
endif

#
# For cleaning, visit each directory for that a corresponding target.mk
# file exists in the source tree. For each such directory, we call
# the single_target rule.
#
clean cleanall::
	@for d in `$(GNU_FIND) -mindepth 1 -type d | $(TAC) | sed "s/^..//"`; do \
		for r in $(REPOSITORIES); do \
			test -f $$r/src/$$d/target.mk && \
				$(MAKE) $(VERBOSE_DIR) single_target \
					SINGLE_SRC=$$r/src/$$d/target.mk \
					ACTION=$@ \
					REP_DIR=$$r || \
				true; \
		done; \
	done

#
# Remove lib cache and library build log
#
clean cleanall::
	$(VERBOSE)rm -rf var/libcache
	$(VERBOSE)rm -f $(LIB_PROGRESS_LOG)

#
# Remove all empty directories
#
clean cleanall::
	$(VERBOSE)$(GNU_FIND) . -depth -type d -empty -delete

#
# Create the place where to install the binaries
#
bin:
	$(VERBOSE)mkdir $@

#
# Rules for building a single target
#
# This rule is only called indirectly by the makefile itself.
#
# We have to use $(shell echo ..) in addition to $(realpath ..)
# for having "~" correctly expanded.
#
PWD           := $(realpath $(shell pwd))
BASE_ABS_DIR  := $(realpath $(shell echo $(BASE_DIR)))
REP_ABS_DIR    = $(realpath $(REP_DIR))
SINGLE_SRC_ABS = $(realpath $(SINGLE_SRC))
SINGLE_SRC_DIR = $(realpath $(dir $(SINGLE_SRC_ABS)))
SINGLE_SRC_TXT = "Processing $(SINGLE_SRC)"
SINGLE_DST     = $(shell echo $(SINGLE_SRC) | sed "s/^.*\/src\///")
SINGLE_DST_DIR = $(dir $(SINGLE_DST))
ACTION        ?= all

single_target: bin
	@echo
	@echo $(SINGLE_SRC_TXT)
	@($(UNDERLINE) && echo $(SINGLE_SRC_TXT) | sed "s/./-/g") || true
	$(VERBOSE)mkdir -p $(SINGLE_DST_DIR)
	$(VERBOSE_MK)$(MAKE) $(VERBOSE_DIR)  -f $(BASE_ABS_DIR)/mk/prg.mk \
       -C $(SINGLE_DST_DIR) \
	  BASE_DIR=$(BASE_ABS_DIR) \
	  REP_DIR=$(REP_ABS_DIR) \
	  PRG_DIR=$(SINGLE_SRC_DIR) \
	  REPOSITORIES="$(realpath $(REPOSITORIES))" \
	  DEFAULT_VPATH=$(SINGLE_SRC_DIR) \
	  INSTALL_DIR=$(PWD)/bin \
	  VERBOSE=$(VERBOSE) \
	  VERBOSE_DIR=$(VERBOSE_DIR) \
	  VERBOSE_MK=$(VERBOSE_MK) \
	  BUILD_BASE_DIR=$(PWD) \
	  LIB_CACHE_DIR=$(LIB_CACHE_DIR) \
	  LIB_PROGRESS_LOG=$(LIB_PROGRESS_LOG) \
	  $(ACTION)
